<template>
  <div class="cesium-draw">
    <div id="cesium-drawer" />
    <canvas id="canvas-a" class="canvas" width="700" height="100"></canvas>
    <canvas id="canvas-b" class="canvas" width="700" height="100"></canvas>
    <div class="mouse-postion">{{ nowPostion.wgs84 }}</div>
    <div id="menu">
      <!--<p><button :class="{active:!!synchronizer}" @click="handleClick('synchronizer')">同步</button></p>
      <p><button :class="{active:isRepeating}" @click="handleClick('isRepeating')">重复</button></p>
      <p><button :class="{active:videoOverlay}" @click="handleClick('videoOverlay')">播放器</button></p> -->
    </div>

    <a-dropdown>
      <a class="ant-dropdown-link tools" @click.prevent>
        {{ drawingModeText }}
        <DownOutlined />
      </a>
      <template #overlay>
        <a-menu @click="handleMenuClick">
          <a-menu-item v-for="(e, index) in menuOptions" :key="e.key">{{ e.text }}</a-menu-item>
        </a-menu>
      </template>
    </a-dropdown>
  </div>
</template>

<script>
import { DownOutlined, EditOutlined } from '@ant-design/icons-vue';
import { defineComponent, ref, watch } from 'vue';
import * as Cesium from '@cesium/Source/Cesium.js';
import MousePosition from '@functional/utils/mousePosition';

export default defineComponent({
  name: 'styPointCloud', // 点云渲染
  components: { DownOutlined, EditOutlined },
  setup() {
    return {
      viewer: null,
      synchronizer: null,
      isRepeating: true,
      videoOverlay: true
    };
  },
  data() {
    return {
      drawingMode: '',
      menuOptions: [
        {
          text: '线',
          key: 'line',
          onselect: () => {}
        }
      ],
      nowPostion: {}
    };
  },
  computed: {
    currOpt() {
      const { drawingMode, menuOptions } = this;
      return menuOptions.filter(e => e.key === drawingMode)[0] || {};
    },
    drawingModeText() {
      const { currOpt } = this;
      return currOpt.text;
    }
  },
  watch: {
    currOpt(opt) {
      opt && opt.onselect();
    }
  },
  mounted() {
    this.initViewer();
  },
  beforeUnmount() {
    if (this.viewer) {
      this.viewer.destroy();
      this.viewer = null;
    }
  },
  methods: {
    handleMenuClick(e) {
      this.drawingMode = e.key;
    },
    onViewerInited(viewer) {
      let vm = this;
      new MousePosition(viewer, pos => {
        vm.nowPostion = pos;
      });
    },
    initViewer() {
      let vm = this;
      Cesium.Ion.defaultAccessToken = $accessToken.default;
      // let osm = new Cesium.OpenStreetMapImageryProvider({
      //   url: 'https://a.tile.openstreetmap.org/'
      // });
      let osm = new Cesium.ArcGisMapServerImageryProvider({
        // url: '//services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer',
        url: '//services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
      });
      var viewer = new Cesium.Viewer('cesium-drawer', {
        imageryProvider: osm,
        contextOptions: {
          webgl: {
            alpha: true
          }
        },
        animation: false,
        // baseLayerPicker: false,
        fullscreenButton: false,
        vrButton: false,
        homeButton: false,
        timeline: false,
        selectionIndicator: false,
        infoBox: false,
        // 注释时相当于使用默认地形，解开注释相当于使用全球地形
        // terrainProvider,
        shouldAnimate: true
      });

      //开启深度检测
      viewer.scene.globe.depthTestAgainstTerrain = true;

      this.viewer = viewer;
      this.onViewerInited(viewer);

      this.initEffects();

      // this.viewer.flyTo(this.viewer.entities);
    },
    initEffects() {
      let vm = this;
      const viewer = this.viewer;

      viewer.clock.currentTime = new Cesium.JulianDate(2457522.154792);

      var tileset = new Cesium.Cesium3DTileset({
        url: '//zzgis.com/cdn/3d/SampleData/Cesium3DTiles/PointCloud/PointCloudWithPerPointProperties/tileset.json'
      });
      viewer.scene.primitives.add(tileset);

      // viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.0, -1.0, 50.0));
      const offset = new Cesium.HeadingPitchRange(0.5, -0.5, 50.0);
      // viewer.zoomTo(tileset, offset);
      viewer.flyTo(tileset, { offset });

      var styles = [];
      function addStyle(name, style) {
        style.pointSize = Cesium.defaultValue(style.pointSize, 5.0);
        styles.push({
          name: name,
          style: style
        });
      }

      addStyle('No Style', {});
      addStyle('Red', {
        color: "color('#ff0000')"
      });

      addStyle('Color Gradient', {
        color: 'color() * ${temperature}'
      });

      addStyle('Step Red/Blue', {
        color: "${temperature} > 0.5 ? color('red') : color('blue')"
      });

      addStyle('Interpolate Red/Blue', {
        color: "color('red') * ${temperature} + color('blue') * (1.0 - ${temperature})"
      });

      addStyle('Color Ramp', {
        color: {
          conditions: [
            ['${temperature} < 0.1', "color('#000099')"],
            ['${temperature} < 0.2', "color('#00cc99', 1.0)"],
            ['${temperature} < 0.3', "color('#66ff33', 0.5)"],
            ['${temperature} < 0.4', 'rgba(255, 255, 0, 0.1)'],
            ['${temperature} < 0.5', 'rgb(255, 128, 0)'],
            ['${temperature} < 0.6', "color('red')"],
            ['${temperature} < 0.7', "color('rgb(255, 102, 102)')"],
            ['${temperature} < 0.8', 'hsl(0.875, 1.0, 0.6)'],
            ['${temperature} < 0.9', 'hsla(0.83, 1.0, 0.5, 0.1)'],
            ['true', "color('#FFFFFF', 1.0)"]
          ]
        }
      });

      addStyle('Transparency', {
        color: 'rgba(0, 255, 0, ${temperature})'
      });

      addStyle('Hide Low Temperature', {
        color: 'rgb(${temperature}*255, 0, 0)',
        show: '${temperature} > 0.3'
      });

      addStyle('Show Subsections', {
        show: '${id} === 1 || ${id} > 250 && ${id} < 300'
      });

      addStyle('Mod', {
        show: '${id} % 2 === 0'
      });

      addStyle('Abs', {
        color: 'color() * abs(${temperature} - 0.5)'
      });

      addStyle('Trigonometric Functions', {
        color: 'color() * radians(cos(${temperature})) + color() * sin(${temperature}) + color() * tan(${temperature})'
      });

      addStyle('Arc Trigonometric Functions', {
        color: 'color() * acos(degrees(${temperature})) + color() * asin(${temperature}) + color() * atan(${temperature}) + color() * atan2(${POSITION}[0],${temperature})'
      });

      addStyle('Sqrt', {
        color: 'color() * sqrt(${temperature})'
      });

      addStyle('Sign', {
        color: 'rgb(sign(${POSITION}[0]) * 255, sign(${POSITION}[1]) * 255, sign(${POSITION}[2]) * 255)'
      });

      addStyle('Rounding Functions', {
        color: 'rgb(floor(${POSITION}[0]) * 255, ceil(${POSITION}[1]) * 255, round(${POSITION}[2]) * 255)'
      });

      addStyle('Exp and Log Functions', {
        color: 'rgb(log(${POSITION}[0]) * 255, log2(${POSITION}[1]) * 255 + exp2(${POSITION}[1]) * 255, exp(${POSITION}[2]) * 255)'
      });

      addStyle('Fractional Part', {
        color: 'rgb(fract(${POSITION}[0]) * 255, fract(${POSITION}[1]) * 255, fract(${POSITION}[2]) * 255)'
      });

      addStyle('Pow', {
        color: 'color() * pow(${temperature}, 3)'
      });

      addStyle('Min and Max', {
        color: 'rgb(min(${POSITION}.x, 0.75) * 255, max(${POSITION}.z, 0.25) * 255, 255)'
      });

      addStyle('Clamp and Mix', {
        color: 'color() * clamp(${temperature}, 0.1, 0.2)'
      });

      addStyle('Secondary Color', {
        color: {
          conditions: [
            ['${id} < 250', 'vec4(${secondaryColor}, 1.0)'],
            ['${id} < 500', 'vec4(${secondaryColor} * ${secondaryColor}, 1.0)'],
            ['${id} < 750', 'vec4(${secondaryColor} / 5.0, 1.0)'],
            ['${id} < 1000', 'rgb(0, 0, Number(${secondaryColor}.x < 0.5) * 255)']
          ]
        }
      });

      addStyle('Use point colors', {
        color: '${COLOR} * ${temperature} + rgb(128,128,128)'
      });

      addStyle('Use point positions', {
        show: '${POSITION}[0] > 0.5 || ${POSITION}[1] > 0.5 || ${POSITION}[2] > 0.5'
      });

      // POSITION contains 0 as its last component, so add 1.0 to make the point cloud opaque
      addStyle('Color based on position', {
        color: 'vec4(${POSITION}, 1.0)'
      });

      addStyle('Style point size', {
        color: "color('red')",
        pointSize: '${temperature} * 10'
      });

      addStyle('Multiple defines', {
        defines: {
          length: 'length(${POSITION})',
          time: '${tiles3d_tileset_time} * 3.0'
        },
        color: {
          conditions: [['${length} < 0.5', "${length} * color('red')"], ['${length} < 1.0', 'vec4(vec3(${temperature} * fract(${time})), 1.0)'], ['true', '${COLOR}']]
        },
        pointSize: '5.0 - ${length} * 2.0',
        show: '${length} < 2.0'
      });

      function setStyle(style) {
        return function() {
          tileset.style = new Cesium.Cesium3DTileStyle(style);
        };
      }

      var styleOptions = [];
      for (var i = 0; i < styles.length; ++i) {
        var style = styles[i];
        styleOptions.push({
          text: style.name,
          key: style.name,
          onselect: setStyle(style.style)
        });
      }

      this.menuOptions = styleOptions;
      this.drawingMode = 'Transparency';
    },
    handleClick(value) {
      const viewer = this.viewer;
      switch (value) {
        case 'isRepeating':
          break;
      }
    }
  }
});
</script>

<style scoped lang="less">
.cesium-draw {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  color: white;
  font-size: 14px;

  #cesium-drawer {
    width: 100%;
    height: 100%;
    overflow: hidden;
    :deep(.cesium-viewer-bottom) {
      display: none !important;
    }
  }

  .mouse-postion {
    position: absolute;
    bottom: 10px;
    right: 10px;
    font-size: 14px;
    padding: 8px 12px;
    line-height: 16px;
    color: white;
    z-index: 9999;
    background-color: rgba(40, 48, 60, 1);
    border-radius: 3px;
    opacity: 0.8;
  }

  .tools {
    position: absolute;
    top: 57px;
    left: 7px;
    font-size: 14px;
    padding: 8px 12px;
    line-height: 16px;
    color: white;
    z-index: 9999;
    background-color: rgba(40, 48, 60, 1);
    border-radius: 3px;
    opacity: 0.6;
    transition: all 500ms;
    &:hover {
      opacity: 0.8;
    }
  }
}

.chart-container {
  position: absolute;
  bottom: 7px;
  left: 7px;
  background-color: rgba(0, 0, 0, 0.5);

  #profileChart {
    width: 600px;
    height: 300px;
  }
}
#canvas-a {
  top: 10px;
  display: none;
}

#canvas-b {
  top: 120px;
  display: none;
}
#trailer {
  position: absolute;
  bottom: 75px;
  right: 0;
  width: 320px;
  height: 180px;
}
#menu {
  position: absolute;
  top: 80px;
  left: 10px;
  z-index: 999;

  button {
    background-color: rgba(0, 0, 0, 0.5);
    border-color: rgba(0, 0, 0, 0);
    cursor: pointer;

    transition: all 500ms;

    &.active {
      background-color: rgba(100, 0, 100, 0.75);
    }

    &:hover {
      opacity: 0.75;
    }
  }
}
</style>
